package com.greenwiki.camera;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.Size;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

//package com.greenwiki.camera;
//
//import java.io.FileNotFoundException;
//import java.io.FileOutputStream;
//import java.io.IOException;
//
//import android.content.Context;
//import android.graphics.Canvas;
//import android.graphics.Color;
//import android.graphics.Paint;
//import android.hardware.Camera;
//import android.hardware.Camera.GeneralPreviewCallback;
//import android.util.Log;
//import android.view.SurfaceHolder;
//import android.view.SurfaceView;
//
//public class GeneralGeneralPreview extends SurfaceView implements
//		SurfaceHolder.Callback {
//
//	private static final String TAG = GeneralGeneralPreview.class.getSimpleName();
//
//	private SurfaceHolder mHolder;
//
//	public Camera camera;
//
//	public GeneralGeneralPreview(Context context) {
//		super(context);
//
//		mHolder = getHolder();
//		mHolder.addCallback(this);
//	}
//
//	@Override
//	public void surfaceChanged(SurfaceHolder holder, int format, int width,
//			int height) {
//		// 2. Get existing (default) settings with getParameters()
//		Camera.Parameters params = camera.getParameters();
//		params.setGeneralPreviewSize(width, height);
//		// 3. If necessary, modify the returned Camera.Parameters object and call setParameters(Camera.Parameters)
//		camera.setParameters(params);
//		// 6. Call startGeneralPreview() to start updating the GeneralPreview surface. 
//		// NOTE: GeneralPreview must be started before you can take a picture.
//		camera.startGeneralPreview();
//	}
//
//	@Override
//	public void surfaceCreated(SurfaceHolder holder) {
//		// 1. Obtain an instance of Camera from open(int).
//		camera = Camera.open();
//		try {
//			// 4. If desired, call setDisplayOrientation(int)
//			// 5. Pass a fully initialized SurfaceHolder to setGeneralPreviewDisplay(SurfaceHolder).
//			// NOTE: Without a surface, the camera will be unable to start the GeneralPreview.
//			camera.setGeneralPreviewDisplay(holder);
//			camera.setGeneralPreviewCallback(new GeneralPreviewCallback() {
//
//				@Override
//				public void onGeneralPreviewFrame(byte[] data, Camera camera) {
//					FileOutputStream fos = null;
//					try {
//						fos = new FileOutputStream(String.format(
//								"/sdcard/%d-%d-%d.jpg",
//								System.currentTimeMillis(), 0, 0));
//						fos.write(data);
//						fos.close();
//
//						Log.d(TAG, "onGeneralPreviewFrame - wrote bytes: "
//								+ data.length);
//					} catch (FileNotFoundException e) {
//						e.printStackTrace();
//					} catch (IOException e) {
//						e.printStackTrace();
//					} finally {
//						
//					}
//					GeneralGeneralPreview.this.invalidate();
//				}
//			});
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
//
//	}
//
//	@Override
//	public void surfaceDestroyed(SurfaceHolder holder) {
//		// 9. Call stopGeneralPreview() to stop updating the GeneralPreview surface
//		camera.stopGeneralPreview();
//		camera = null;
//	}
//
////	/* (non-Javadoc)
////	 * @see android.view.SurfaceView#draw(android.graphics.Canvas)
////	 */
////	@Override
////	public void draw(Canvas canvas) {
////		super.draw(canvas);
////		
////		Paint p = new Paint(Color.RED);
////		Log.d(TAG, "draw");
////		canvas.drawText("GeneralPreview", canvas.getWidth() / 2, canvas.getHeight() / 2, p);
////	}
//
//	
//}

class GeneralPreview extends SurfaceView implements SurfaceHolder.Callback {
	private static final String TAG = GeneralPreview.class.getSimpleName();
	
    SurfaceHolder mHolder;
    Camera mCamera;

    GeneralPreview(Context context) {
        super(context);

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, acquire the camera and tell it where
        // to draw.
        mCamera = Camera.open();
        try {
           mCamera.setPreviewDisplay(holder);
           mCamera.setPreviewCallback(new PreviewCallback() {
           
           				@Override
           				public void onPreviewFrame(byte[] data, Camera camera) {
           					FileOutputStream fos = null;
           					try {
           						fos = new FileOutputStream(String.format(
           								"/sdcard/%d-%d-%d.jpg",
           								System.currentTimeMillis(), 0, 0));
           						fos.write(data);
           						fos.close();
           
           						Log.d(TAG, "onGeneralPreviewFrame - wrote bytes: "
           								+ data.length);
           					} catch (FileNotFoundException e) {
           						e.printStackTrace();
           					} catch (IOException e) {
           						e.printStackTrace();
           					} finally {
           						
           					}
           					GeneralPreview.this.invalidate();
           				}
           			});
           
        } catch (IOException exception) {
            mCamera.release();
            mCamera = null;
            // TODO: add more exception handling logic here
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // Surface will be destroyed when we return, so stop the GeneralPreview.
        // Because the CameraDevice object is not a shared resource, it's very
        // important to release it when the activity is paused.
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }


    private Size getOptimalGeneralPreviewSize(List<Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.05;
        double targetRatio = (double) w / h;
        if (sizes == null) return null;

        Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        // Try to find an size match aspect ratio and size
        for (Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        // Cannot find the one match the aspect ratio, ignore the requirement
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // Now that the size is known, set up the camera parameters and begin
        // the GeneralPreview.
        Camera.Parameters parameters = mCamera.getParameters();

        List<Size> sizes = parameters.getSupportedPreviewSizes();
        Size optimalSize = getOptimalGeneralPreviewSize(sizes, w, h);
        parameters.setPreviewSize(optimalSize.width, optimalSize.height);

        mCamera.setParameters(parameters);
        mCamera.startPreview();
    }

}